package aole.mindfx.model;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import aole.mindfx.FXNodeListener;

public class AppStructure {
	private HashMap< String, MindFXClass >	classList	= new HashMap<>();
	private FXNodeListener					listener;

	public AppStructure( FXNodeListener l ) {
		listener = l;
	}

	public void load( File fXmlFile ) throws ParserConfigurationException,
			SAXException, IOException {
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse( fXmlFile );
		doc.getDocumentElement().normalize();

		getClasses( doc );
	}

	public void save( File fXmlFile ) throws ParserConfigurationException,
			TransformerException {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
		// root elements
		Document doc = docBuilder.newDocument();
		Element rootElement = doc.createElement( "mindfx" );

		// classes elements
		Element classes = doc.createElement( "classes" );
		for( MindFXClass c: classList.values() ) {

			// class elements
			Element ce = doc.createElement( c.getName() );
			classes.appendChild( ce );
			c.saveXML(doc, ce);
		}
		rootElement.appendChild( classes );
		doc.appendChild( rootElement );

		// write the content into xml file
		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		Transformer transformer = transformerFactory.newTransformer();
		DOMSource source = new DOMSource( doc );
		StreamResult result = new StreamResult( fXmlFile );
		transformer.transform( source, result );
	}

	private void getClasses( Document doc ) {
		NodeList nList = doc.getElementsByTagName( "classes" );
		Node classes = nList.item( 0 );

		for( Node c = classes.getFirstChild(); c != null; c = c
				.getNextSibling() ) {
			if( c.getNodeType() == Node.ELEMENT_NODE ) {
				String name = c.getNodeName();
				MindFXClass fxclass = new MindFXClass( name, listener );
				classList.put( name, fxclass );
				fxclass.loadXML(c);// TODO: 
			}
		}
	}

	public Collection< MindFXClass > getAllClasses() {
		return classList.values();
	}

	public void addFXClass( MindFXClass c ) {
		classList.put( c.getName(), c );
	}

	public MindFXClass getFXClass( String type ) {
		return classList.get( type );
	}

	public void deleteFXNode( MindFXClass c ) {
		classList.remove( c );
	}

	public void deleteFXNode( MindFXMethod m ) {
		MindFXClass c = m.getFXClass();
		c.deleteFXMethod(m);
	}

	public void deleteFXNode( MindFXAttribute a ) {
		MindFXClass c = a.getParent();
		c.deleteFXAttribute(a);
	}

	public void deleteFXNode( MindFXCall c ) {
		MindFXMethod m = c.getParent();
		m.deleteFXCall(c);
	}
}
